WebGLda real vaqtda soyalarni render qilishning asosiy tushunchalari va ilg'or usullarini o'rganing. Ushbu qo'llanmada soyani xaritalash, PCF, CSM va umumiy artefaktlarga yechimlar ko'rib chiqiladi.
WebGL Soyani xaritalash: Real-time rendering bo'yicha keng qamrovli qo'llanma
3D kompyuter grafikasi dunyosida, ozgina elementlar soyalardan ko'proq realizm va immersiyaga hissa qo'shadi. Ular ob'ektlar orasidagi fazoviy munosabatlar, yorug'lik manbalarining joylashuvi va sahna geometriyasi haqida muhim vizual ma'lumotlarni taqdim etadi. Soyalarsiz, 3D dunyosi tekis, uzilgan va sun'iy tuyulishi mumkin. WebGL bilan ishlaydigan veb-asosidagi 3D ilovalari uchun yuqori sifatli, real vaqtda soyalarni amalga oshirish professional darajadagi tajribalarning belgisi hisoblanadi. Ushbu qo'llanma buni amalga oshirishning eng asosiy va keng qo'llaniladigan usuli bo'yicha chuqur tahlilni taqdim etadi: Soyani xaritalash.
Siz tajribali grafik dasturchi yoki uchinchi o'lchovga kirayotgan veb-ishlab chiquvchi bo'lasizmi, bu maqola sizni WebGL loyihalarida real vaqtda soyalarni tushunish, amalga oshirish va muammolarni bartaraf etish uchun bilim bilan ta'minlaydi. Biz asosiy nazariyadan amaliy amalga oshirish tafsilotlarigacha sayohat qilamiz, umumiy kamchiliklar va zamonaviy grafik dvigatellarida qo'llaniladigan ilg'or texnikalarni o'rganamiz.
1-bob: Soyani xaritalash asoslari
Asosan, soyani xaritalash - bu sahnadagi nuqta soyada ekanligini aniqlashning aqlli va oqlangan usuli, oddiy savol berish orqali: "Ushbu nuqtani yorug'lik manbai ko'rishi mumkinmi?" Agar javob yo'q bo'lsa, demak, nimanidir yorug'likni to'sib qo'yadi va nuqta soyada bo'lishi kerak. Ushbu savolga dasturiy jihatdan javob berish uchun biz ikki bosqichli rendering yondashuvidan foydalanamiz.
Soyani xaritalash nima? Asosiy tushuncha
Butun texnika ikki marta, har safar boshqa nuqtai nazardan sahnani render qilish atrofida aylanadi:
- 1-pass: Chuqurlik o'tishi (Yorug'likning nuqtai nazari). Birinchidan, biz butun sahnani yorug'lik manbasining aniq pozitsiyasi va yo'nalishidan render qilamiz. Biroq, biz bu o'tishda ranglar yoki teksturalarga ahamiyat bermaymiz. Bizga kerak bo'lgan yagona ma'lumot - bu chuqurlik. Render qilingan har bir ob'ekt uchun biz uning yorug'lik manbaidan masofasini qayd etamiz. Chuqurlik qiymatlarining bu to'plami soya xaritasi yoki chuqurlik xaritasi deb nomlangan maxsus teksturada saqlanadi. Ushbu xaritaning har bir pikseli ma'lum bir yo'nalishdagi yorug'lik nuqtasidan eng yaqin ob'ektgacha bo'lgan masofani ifodalaydi.
- 2-pass: Sahna o'tishi (Kameraning nuqtai nazari). Keyin, biz sahnani odatdagidek, asosiy kameraning nuqtai nazaridan render qilamiz. Lekin chizilayotgan har bir piksel uchun biz qo'shimcha hisob-kitoblar olib boramiz. Biz ushbu pikselning 3D fazosidagi pozitsiyasini aniqlaymiz va keyin so'raymiz: "Ushbu nuqta yorug'lik manbaidan qanday masofada?" Keyin biz bu masofani tegishli joydagi soya xaritamizda (1-o'tishdan) saqlangan qiymat bilan taqqoslaymiz.
Mantiq oddiy:
- Agar pikselning yorug'likdan joriy masofasi soya xaritasida saqlangan masofadan katta bo'lsa, demak, bir xil ko'rish chizig'ida yorug'likka yaqinroq boshqa ob'ekt mavjud. Shuning uchun, joriy piksel soyada.
- Agar pikselning masofasi soya xaritasidagi masofadan kichik yoki unga teng bo'lsa, demak, uni hech narsa to'sib qo'ymaydi va piksel to'liq yoritilgan.
Sahnani sozlash
WebGLda soyani xaritalashni amalga oshirish uchun sizga bir nechta asosiy komponentlar kerak:
- Yorug'lik manbai: Bu yo'naltiruvchi yorug'lik (quyosh kabi), nuqta yorug'ligi (lampochka kabi) yoki spot yorug'ligi bo'lishi mumkin. Yorug'lik turi chuqurlik o'tishida ishlatiladigan proyeksiyani aniqlaydi.
- Framebuffer Ob'ekti (FBO): WebGL odatda ekranning standart freymbufferiga render qiladi. Soya xaritamizni yaratish uchun bizga ekran tashqarisidagi render maqsadi kerak. FBO bizga ekranning o'rniga teksturada render qilishga imkon beradi. Bizning FBO chuqurlik teksturasi biriktirilgan holda sozlanadi.
- Ikkita Shaderlar to'plami: Sizga chuqurlik o'tishi uchun bitta shader dasturi (juda oddiy) va yakuniy sahna o'tishi uchun boshqa shader dasturi (soya hisoblash mantig'ini o'z ichiga oladi) kerak bo'ladi.
- Matritsalar: Sizga kameraning standart model, ko'rinish va proyeksion matritsalari kerak bo'ladi. Muhimi, sizga yorug'lik manbai uchun ko'rinish va proyeksion matritsasi ham kerak bo'ladi, ular ko'pincha bitta "yorug'lik fazosi matritsasi" ga birlashtiriladi.
2-bob: Ikki bosqichli rendering liniyasini batafsil
Keling, ikki rendering o'tishini bosqichma-bosqich ko'rib chiqaylik, matritsalar va shaderlarning rollariga e'tibor qaratamiz.
1-pass: Chuqurlik o'tishi (Yorug'likning nuqtai nazaridan)
Ushbu o'tishning maqsadi - chuqurlik teksturasini to'ldirish. U qanday ishlashi bilan tanishing:
- FBO ni bog'lang: Chizishdan oldin, siz WebGLga kanvas o'rniga o'z FBOga render qilishni buyurasiz.
- Viewportni sozlang: Viewport o'lchamlarini soya xaritangiz teksturasi o'lchamlariga mos ravishda o'rnating (masalan, 1024x1024 piksel).
- Chuqurlik buferini tozalang: Renderingdan oldin FBO ning chuqurlik bufferi tozalanganligiga ishonch hosil qiling.
- Yorug'likning matritsalarini yarating:
- Yorug'lik ko'rinishi matritsasi: Ushbu matritsa dunyoni yorug'likning nuqtai nazariga o'zgartiradi. Yo'naltiruvchi yorug'lik uchun bu odatda `lookAt` funksiyasi bilan yaratiladi, bunda "ko'z" yorug'likning holati va "maqsad" u ko'rsatayotgan yo'nalishdir.
- Yorug'lik proyeksiyasi matritsasi: Parallel nurlarga ega bo'lgan yo'naltiruvchi yorug'lik uchun ortografik proyeksiyadan foydalaniladi. Nuqta yorug'lik yoki spot yorug'ligi uchun perspektiv proyeksiyadan foydalaniladi. Ushbu matritsa fazodagi hajmni (quti yoki frustum) aniqlaydi, u soyalarni yaratadi.
- Chuqurlik Shader dasturini foydalaning: Bu minimal shader. Vertex shaderning yagona vazifasi - vertex pozitsiyasini yorug'likning ko'rinishi va proyeksion matritsalariga ko'paytirishdir. Fragment shader undan ham oddiy: u faqat fragmentning chuqurlik qiymatini (uning z-koordinatasi) chuqurlik teksturasiga yozadi. Zamonaviy WebGLda, siz hatto maxsus fragment shaderga muhtoj emassiz, chunki FBO chuqurlik bufferini avtomatik ravishda ushlab turish uchun sozlanishi mumkin.
- Sahnani render qiling: Sahnadagi barcha soya tashlovchi ob'ektlarni chizing. FBO endi bizning yakuniy soya xaritamizni o'z ichiga oladi.
2-pass: Sahna o'tishi (Kameraning nuqtai nazaridan)
Endi biz soyalarni aniqlash uchun yaratgan soya xaritamizdan foydalanib, yakuniy tasvirni render qilamiz.
- FBO ni bog'lang: Standart kanvas freymbufferiga renderingga qayting.
- Viewportni sozlang: Viewportni kanvas o'lchamlariga qaytaring.
- Ekranni tozalang: Kanvasning rangli va chuqurlik buferlarini tozalang.
- Sahna Shader dasturini foydalaning: Bu erda sehr sodir bo'ladi. Bu shader murakkabroq.
- Vertex Shader: Ushbu shader ikki narsani bajarishi kerak. Birinchidan, u odatdagidek kameraning model, ko'rinish va proyeksion matritsalaridan foydalanib, yakuniy vertex pozitsiyasini hisoblab chiqadi. Ikkinchidan, u shuningdek, 1-o'tishdagi yorug'lik fazosi matritsasidan foydalanib, vertexning pozitsiyasini yorug'lik nuqtai nazaridan hisoblashi kerak. Ushbu ikkinchi koordinata fragment shaderga o'zgaruvchi sifatida o'tkaziladi.
- Fragment Shader: Bu soya mantiqining asosi. Har bir fragment uchun:
- Vertex shaderdan yorug'lik fazosida interpolatsiya qilingan pozitsiyani oling.
- Ushbu koordinataga perspektivaga bo'lishni bajaring (x, y, z ni w ga bo'ling). Bu uni normalangan qurilma koordinatalariga (NDC) aylantiradi, -1 dan 1 gacha.
- NDC ni tekstura koordinatalariga (0 dan 1 gacha bo'lgan) aylantiring, shuning uchun biz soya xaritamizni namuna olamiz. Bu oddiy o'lchov va bias operatsiyasi: `texCoord = ndc * 0.5 + 0.5;`.
- 1-o'tishda yaratilgan soya xaritamiz teksturasini namuna olish uchun ushbu tekstura koordinatalaridan foydalaning. Bu bizga `depthFromShadowMap` beradi.
- Fragmentning yorug'lik nuqtai nazaridan joriy chuqurligi - bu uning transformatsiyalangan yorug'lik fazosi koordinatasidan z-komponenti. Keling, uni `currentDepth` deb ataylik.
- Chuqurliklarni taqqoslang: Agar `currentDepth > depthFromShadowMap`, fragment soyada. Biz keyingi muhokama qiladigan "soya aknesi" deb nomlangan artefaktning oldini olish uchun ushbu tekshiruvga kichik bias qo'shishimiz kerak bo'ladi.
- Taqqoslashga asoslanib, soya faktorini aniqlang (masalan, yoritilgan uchun 1.0, soyali uchun 0.3).
- Ushbu soya faktorini yakuniy rang hisobiga qo'llang (masalan, ambient va diffuz yoritish komponentlarini soya faktoriga ko'paytiring).
- Sahnani render qiling: Sahnadagi barcha ob'ektlarni chizing.
3-bob: Umumiy muammolar va yechimlar
Asosiy soyani xaritalashni amalga oshirish bir nechta umumiy vizual artefaktlarni tezda ochib beradi. Ularni tushunish va tuzatish yuqori sifatli natijalarga erishish uchun juda muhimdir.
Soya aknesi (O'z-o'zini soyalash artefaktlari)
Muammo: Siz to'liq yoritilishi kerak bo'lgan yuzalarda g'alati, noto'g'ri qora chiziqlar yoki Moiréga o'xshash naqshlarni ko'rishingiz mumkin. Bu "soya aknesi" deb ataladi. Bu soya xaritasida saqlangan chuqurlik qiymati va sahna o'tish paytida hisoblangan chuqurlik qiymati bir xil sirt uchun bo'lganligi sababli yuzaga keladi. Suzuvchi nuqta noaniqliklari va soya xaritasining cheklangan aniqligi tufayli, kichik xatolar fragmentning o'zini noto'g'ri aniqlashiga olib kelishi mumkin, bu esa o'z-o'zini soyalashga olib keladi.
Yechim: Chuqurlik Bias. Eng oddiy yechim - taqqoslashdan oldin `currentDepth` ga kichik bias kiritishdir. Fragmentni aslida bo'lganidan bir oz yorug'likka yaqinroq ko'rinishini ta'minlash orqali, biz uni o'z soyasidan "chiqarib" tashlaymiz.
float shadow = currentDepth > depthFromShadowMap + bias ? 0.3 : 1.0;
To'g'ri bias qiymatini topish nozik muvozanatdir. Juda kichik, va akne qoladi. Juda katta, va siz keyingi muammoni olasiz.
Piter Panning
Muammo: Ushbu artefakt, soyasini yo'qotgan va ucha oladigan qahramon sharafiga nomlangan, ob'ekt va uning soyasi o'rtasidagi ko'rinadigan bo'shliq sifatida namoyon bo'ladi. Bu ob'ektlar suzayotgandek yoki ular dam olayotgan yuzalaridan uzilgan ko'rinishini ta'minlaydi. Bu juda katta chuqurlik biasidan foydalanishning bevosita natijasidir.
Yechim: Qiyalik o'lchovi Chuqurlik Bias. Doimiy biasdan ko'ra mustahkamroq yechim - biasni yorug'likka nisbatan sirtning tikligiga bog'liq qilishdir. Tikroq ko'pburchaklar aknega ko'proq moyil bo'ladi va kattaroq bias talab qiladi. Tekisroq ko'pburchaklar kichikroq bias kerak. WebGL kabi ko'pgina grafik APIlar, fragment shaderdagi qo'lda biasdan ko'ra afzalroq bo'lgan, chuqurlik o'tishida avtomatik ravishda ushbu turdagi biasni qo'llash funktsiyasini taqdim etadi.
Perspektiv aliasing (Tirajali qirralar)
Muammo: Soyalaringizning qirralari blokli, tiralik va pikselga o'xshash ko'rinadi. Bu aliasingning bir shakli. Bu soya xaritasining aniqligi cheklanganligi sababli yuzaga keladi. Soya xaritasidagi bitta piksel (yoki tektsel) yakuniy sahndagi yuzada katta maydonni qoplashi mumkin, ayniqsa kameraga yaqin yoki siljish burchagida ko'riladigan yuzalar uchun. Aniqsizlikdagi bu nomuvofiqlik xarakterli blokli ko'rinishga olib keladi.
Yechim: Soya xaritasi ruxsatini oshirish (masalan, 1024x1024 dan 4096x4096 gacha) yordam berishi mumkin, ammo u muhim xotira va ishlash xarajatlariga olib keladi va asosiy muammoni to'liq hal qilmaydi. Haqiqiy yechimlar yanada ilg'or usullarda yotadi.
4-bob: Ilg'or soyani xaritalash texnikasi
Asosiy soyani xaritalash poydevorni ta'minlaydi, ammo professional ilovalar uning cheklovlarini, ayniqsa aliasingni engish uchun yanada murakkab algoritmlardan foydalanadi.
Foizga yaqinroq filtrlash (PCF)
PCF soyali qirralarni yumshatish va aliasingni kamaytirish uchun eng keng tarqalgan usuldir. Soya xaritasidan bitta namunani olish va ikkilik (soyada yoki soyada emas) qaror qabul qilish o'rniga, PCF maqsad koordinatasi atrofidagi sohadan bir nechta namunalarni oladi.
Tushuncha: Har bir fragment uchun biz soya xaritasini bir marta emas, balki fragmentning proyeksiyalashtirilgan tekstura koordinatasi atrofida grid naqshida (masalan, 3x3 yoki 5x5) namuna olamiz. Ushbu namunalarning har biri uchun biz chuqurlikni taqqoslaymiz. Yakuniy soya qiymati ushbu taqqoslashlarning o'rtachasi hisoblanadi. Masalan, agar 9 ta namunadan 4 tasi soyada bo'lsa, fragment 4/9 soyali bo'ladi, bu esa silliq penumbra (soyalar soyasining yumshoq qirrasi)ga olib keladi.
Amalga oshirish: Bu butunlay fragment shader ichida amalga oshiriladi. Bu kichik yadro bo'ylab iteratsiya qiladigan, soya xaritasini har bir ofsetda namuna oladigan va natijalarni to'playdigan pastadirni o'z ichiga oladi. WebGL 2 apparat yordamini taklif etadi (`sampler2DShadow` bilan `texture`), bu taqqoslash va filtrlashni samaraliroq amalga oshirishi mumkin.
Foyda: Qattiq, aliased qirralarni silliq, yumshoq qirralarga almashtirish orqali soyalarning sifatini keskin yaxshilaydi.
Narxi: Har bir fragment uchun olingan namunalarning soni bilan ishlash pasayadi.
Kaskadli soya xaritalari (CSM)
CSM - bu juda katta sahnada (quyosh kabi) bitta yo'naltiruvchi yorug'lik manbasidan soyalarni render qilishning sanoat standarti yechimidir. U perspektivali aliasing muammosini bevosita hal qiladi.
Tushuncha: Asosiy g'oya shundaki, kameraga yaqin ob'ektlar uzoqdagi ob'ektlarga qaraganda ancha yuqori soya ruxsatiga muhtoj. CSM kameraning ko'rinish frustumini uning chuqurligi bo'ylab bir nechta bo'limlarga yoki "kaskadlarga" ajratadi. Keyin har bir kaskad uchun alohida, yuqori sifatli soya xaritasi render qilinadi. Kameraga eng yaqin kaskad dunyo makonining kichik maydonini qoplaydi va shu tariqa juda yuqori samarali ruxsatga ega. Uzoqroq kaskadlar bir xil tekstura o'lchami bilan progressiv ravishda katta maydonlarni qoplaydi, bu maqbuldir, chunki bu tafsilotlar o'yinchiga kamroq ko'rinadi.
Amalga oshirish: Bu sezilarli darajada murakkabroq.
- Protsessorda kamera frustumini 2-4 kaskadga bo'ling.
- Har bir kaskad uchun frustumning shu qismiga mukammal tarzda o'ralgan yorug'lik uchun zich mos keladigan ortografik proyeksion matritsasini hisoblang.
- Rendering pastadirida, chuqurlikni o'tishni bir necha marta bajaring - har bir kaskad uchun, har xil soya xaritasiga (yoki tekstura atlasining mintaqasiga) render qilish.
- Yakuniy sahna o'tish fragment shaderida joriy fragment kameradan masofaga qarab qaysi kaskadga tegishli ekanligini aniqlang.
- Soyani hisoblash uchun tegishli kaskadning soya xaritasini namuna oling.
Foyda: Katta masofalarda izchil yuqori ruxsatli soyalarni ta'minlaydi, bu uni ochiq havoda muhitlar uchun mukammal qiladi.
Variatsiya soya xaritalari (VSM)
VSM - yumshoq soyalarni yaratishning yana bir usuli, ammo u PCFdan farqli yondashuvni qabul qiladi.
Tushuncha: Soya xaritasida faqat chuqurlikni saqlash o'rniga, VSM ikkita qiymatni saqlaydi: chuqurlik (birinchi moment) va chuqurlik kvadrati (ikkinchi moment). Ushbu ikkita qiymat bizga chuqurlik taqsimotining o'zgarishini hisoblashga imkon beradi. Chebyshev tengsizligi deb nomlangan matematik vositadan foydalanib, biz fragmentning soyada bo'lish ehtimolini baholashimiz mumkin. Asosiy afzalligi shundaki, VSM teksturasini standart apparat tomonidan tezlashtirilgan chiziqli filtrlash va mipmapping yordamida xiralashtirish mumkin, bu standart chuqurlik xaritasi uchun matematik jihatdan noto'g'ri. Bu juda katta, yumshoq va silliq soya penumbralari uchun belgilangan ishlash xarajatlari bilan imkon beradi.
Kamchilik: VSM ning asosiy kamchiligi - "yorug'lik oqishi", bu erda yorug'lik statistik yaqinlashuv buzilishi mumkin bo'lgan vaziyatlarda, ob'ektlardan o'tib ketishi mumkin.
5-bob: Amaliy amalga oshirish bo'yicha maslahatlar va ishlash
Soya xaritangizning aniqligini tanlash
Soya xaritasining aniqligi sifat va ishlash o'rtasidagi bevosita savdodir. Katta tekstura o'tkirroq soyalarni ta'minlaydi, ammo ko'proq video xotirasini iste'mol qiladi va render qilish va namuna olish uchun ko'proq vaqt oladi. Umumiy o'lchamlar quyidagilarni o'z ichiga oladi:
- 1024x1024: Ko'pgina ilovalar uchun yaxshi asos.
- 2048x2048: Ish stoli ilovalari uchun sifatning sezilarli darajada yaxshilanishini taklif qiladi.
- 4096x4096: Yuqori sifatli, ko'pincha qahramon aktivlari yoki kuchli cullingga ega bo'lgan dvigatellarda ishlatiladi.
Yorug'likning frustumini optimallashtirish
Soya xaritasidagi har bir pikseldan maksimal foyda olish uchun, yorug'likning proyeksion hajmi (uning ortografik qutisi yoki perspektiv frustum) soyalarga muhtoj bo'lgan sahna elementlariga iloji boricha mahkam moslashtirilishi muhim. Yo'naltiruvchi yorug'lik uchun, bu uning ortografik proyeksiyasi faqat kameraning frustumining ko'rinadigan qismini o'z ichiga olishini anglatadi. Soya xaritasidagi har qanday isrof qilingan joy - bu isrof qilingan ruxsatdir.
WebGL kengaytmalari va versiyalari
WebGL 1 vs. WebGL 2: WebGL 1 da soyani xaritalash mumkin bo'lsa-da, WebGL 2 da u ancha oson va samaraliroq. WebGL 1 chuqurlik teksturasini yaratish uchun `WEBGL_depth_texture` kengaytmasini talab qiladi. WebGL 2 bu funksiyani o'rnatgan. Bundan tashqari, WebGL 2 soya namunalari (`sampler2DShadow`) ga kirishni ta'minlaydi, bu shaderdagi qo'lda PCF pastadirlariga nisbatan sezilarli ishlash yaxshilanishini taklif etuvchi apparat tomonidan tezlashtirilgan PCF ni bajarishi mumkin.
Soyalarni disk raskadrovka qilish
Soyalarni disk raskadrovka qilish qiyin bo'lishi mumkin. Eng foydali texnika - soya xaritasini vizualizatsiya qilishdir. Ilovangizni vaqtinchalik o'zgartiring, ma'lum bir yorug'lik manbaidan chuqurlik teksturasini to'g'ridan-to'g'ri ekrandagi kvadga render qilish uchun. Bu yorug'likning "ko'rgan" narsalarini aniq ko'rishga imkon beradi. Bu yorug'lik matritsalarida, frustum cullingida yoki chuqurlik o'tish paytida ob'ektni render qilishda muammolarni darhol aniqlashi mumkin.
Xulosa
Real vaqtda soyani xaritalash zamonaviy 3D grafikasining asosiy toshidir, tekis, hayotsiz sahnalarni ishonchli va dinamik dunyoga aylantiradi. Yorug'lik nuqtai nazaridan render qilish tushunchasi oddiy bo'lsa-da, yuqori sifatli, artefaktsiz natijalarga erishish ikki bosqichli quvurlardan tortib, chuqurlik bias va aliasingning nozik nuqtalarigacha bo'lgan asosiy mexanikalarni chuqur tushunishni talab qiladi.
Asosiy amalga oshirishdan boshlab, siz soya aknesi va tirajali qirralar kabi umumiy artefaktlarni bosqichma-bosqich hal qilishingiz mumkin. U yerdan siz yumshoq soyalar uchun PCF yoki keng ko'lamli muhitlar uchun Kaskadli Soya Xaritalari kabi ilg'or texnikalar bilan vizuallaringizni ko'tarishingiz mumkin. Soya renderiga sayohat kompyuter grafikasini juda jozibador qiladigan san'at va fanning aralashmasining mukammal namunasidir. Sizni ushbu texnikalar bilan tajriba o'tkazishga, ularning chegaralarini itarishga va WebGL loyihalariga yangi realizm darajasini olib kelishga undaymiz.